/*
 * This file is part of TradeHelper library.
 *
 * TradeHelper library is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * TradeHelper library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with TradeHelper library.  If not, see <http://www.gnu.org/licenses/>.
 */

package com.rag.forum;

import com.alee.extended.breadcrumb.BreadcrumbElementType;
import com.alee.extended.breadcrumb.WebBreadcrumb;
import com.alee.extended.breadcrumb.WebBreadcrumbToggleButton;
import com.alee.extended.drag.ProxyDropHandler;
import com.alee.extended.image.WebImage;
import com.alee.extended.label.WebLinkLabel;
import com.alee.extended.layout.SlidingLayout;
import com.alee.extended.panel.GroupPanel;
import com.alee.laf.StyleConstants;
import com.alee.laf.WebLookAndFeel;
import com.alee.laf.button.WebButton;
import com.alee.laf.label.WebLabel;
import com.alee.laf.panel.WebPanel;
import com.alee.laf.scroll.WebScrollBarStyle;
import com.alee.laf.separator.WebSeparatorStyle;
import com.alee.managers.hotkey.Hotkey;
import com.alee.managers.hotkey.HotkeyManager;
import com.alee.managers.hotkey.HotkeyRunnable;
import com.alee.managers.popup.PopupManager;
import com.alee.managers.popup.PopupWay;
import com.alee.managers.popup.WebButtonPopup;
import com.alee.managers.settings.SettingsManager;
import com.alee.managers.tooltip.TooltipManager;
import com.alee.utils.SwingUtils;
import com.alee.utils.TextUtils;
import com.alee.utils.WebUtils;
import com.rag.core.ForumType;
import com.rag.core.Item;
import com.rag.core.SingleNews;
import com.rag.core.TrackerPage;
import com.rag.forum.pages.*;
import com.rag.forum.ui.ItemDropList;
import com.rag.forum.ui.ItemField;
import com.rag.forum.ui.ItemSelectionListener;
import com.rag.managers.*;
import com.rag.managers.update.NewsListener;
import com.rag.managers.update.UpdateListener;
import info.clearthought.layout.TableLayout;

import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;

/**
 * User: mgarin Date: 04.04.12 Time: 14:32
 */

public class TradeHelper extends JFrame
{
    private static Image icon =
            new ImageIcon ( TradeHelper.class.getResource ( "icons/icon.png" ) ).getImage ();
    private static Image loadIcon =
            new ImageIcon ( TradeHelper.class.getResource ( "icons/load.gif" ) ).getImage ();

    private static ImageIcon itemsCanIcon =
            new ImageIcon ( TradeHelper.class.getResource ( "icons/menu/itemsCan.png" ) );

    private static TradeHelper instance;

    // Открытая страница

    private TrackerPage page;

    // UI

    private WebPanel topPanel;
    private SlidingLayout slidingLayout;

    private WebBreadcrumb menu;
    private HashMap<TrackerPage, WebBreadcrumbToggleButton> pageButtons;

    private WebPanel contentPanel;
    private CardLayout contentLayout;

    private TrayIcon trayIcon;
    private MenuItem hideItem;

    public static void main ( String[] args )
    {
        // Настройки стилизации
        WebScrollBarStyle.scrollBorder = StyleConstants.borderColor;
        WebSeparatorStyle.drawSideLines = false;
        StyleConstants.disabledIconsTransparency = 0.5f;

        // Установка внешнего вида приложения
        WebLookAndFeel.install ();

        // Инициализируем базовые настройки приложения
        BaseManager.initialize ();

        // Проверяем обновления
        UpdateManager.initialize ( new UpdateListener ()
        {
            public void updateComplete ()
            {
                // Инициализируем прочие менеджеры
                RagManager.initialize ();
                UsersManager.initializeManager ();
                FavoritesManager.initializeManager ();

                // Запускаем
                instance = new TradeHelper ();
            }
        } );
    }

    public static TradeHelper getInstance ()
    {
        return instance;
    }

    public TradeHelper ()
    {
        super ( "Помощник Торговца" );
        setIconImages ( WebLookAndFeel.getImages () );

        setLayout ( new TableLayout ( new double[][]{ { TableLayout.FILL },
                { TableLayout.PREFERRED, TableLayout.PREFERRED, TableLayout.FILL,
                        TableLayout.PREFERRED } } ) );

        ////////////////////////////////////////////////////////////

        HotkeyManager.registerHotkey ( this, Hotkey.ESCAPE, new HotkeyRunnable ()
        {
            public void run ( KeyEvent e )
            {
                PopupManager.hideAllPopups ();
            }
        } );
        HotkeyManager.registerHotkey ( this, Hotkey.TAB, new HotkeyRunnable ()
        {
            public void run ( KeyEvent e )
            {
                TrackerPage[] pages = TrackerPage.values ();
                int current = Arrays.asList ( pages ).indexOf ( page );
                if ( current < pages.length - 1 )
                {
                    switchToPage ( pages[ current + 1 ] );
                }
                else
                {
                    switchToPage ( pages[ 0 ] );
                }
            }
        } );
        HotkeyManager.registerHotkey ( this, Hotkey.SHIFT_TAB, new HotkeyRunnable ()
        {
            public void run ( KeyEvent e )
            {
                TrackerPage[] pages = TrackerPage.values ();
                int current = Arrays.asList ( pages ).indexOf ( page );
                if ( current > 0 )
                {
                    switchToPage ( pages[ current - 1 ] );
                }
                else
                {
                    switchToPage ( pages[ pages.length - 1 ] );
                }
            }
        } );

        ////////////////////////////////////////////////////////////

        //        WebStatusBar statusBar = new WebStatusBar ();
        //        add ( statusBar, "0,3" );
        //
        //        WebMemoryBar memoryBar = new WebMemoryBar ();
        //        memoryBar.setPreferredWidth ( 150 );
        //        statusBar.addToEnd ( memoryBar );

        ////////////////////////////////////////////////////////////

        topPanel = new WebPanel ( true );
        topPanel.setDrawSides ( false, false, true, false );
        topPanel.setWebColored ( false );
        topPanel.setShadeWidth ( 0 );
        slidingLayout = new SlidingLayout ( topPanel );
        slidingLayout.setSlideSpeed ( 6 );
        topPanel.setLayout ( slidingLayout );
        add ( topPanel, "0,0" );

        final WebPanel titlePanel = new WebPanel ( new BorderLayout ( 10, 10 ) );
        titlePanel.setOpaque ( false );
        titlePanel.setMargin ( 10 );
        titlePanel.addMouseListener ( new MouseAdapter ()
        {
            public void mousePressed ( MouseEvent e )
            {
                slidingLayout.slideOut ();
            }
        } );
        topPanel.add ( titlePanel );

        final WebLabel newsIcon = new WebLabel ();
        titlePanel.add ( newsIcon, BorderLayout.WEST );

        final WebLabel newsTitle = new WebLabel ();
        newsTitle.setMargin ( 0, 0, 4, 0 );
        final WebLabel newsText = new WebLabel ();
        final WebLinkLabel newsLink = new WebLinkLabel ();
        titlePanel.add ( new GroupPanel ( 0, false, newsTitle, newsText,
                new GroupPanel ( newsLink ) ), BorderLayout.CENTER );

        // Проверка новостей на сервере
        UpdateManager.addNewsListener ( new NewsListener ()
        {
            public void announceUpdated ( SingleNews announceNews )
            {
                // Анонсы никак не показываем, их всегда можно найти на странице новостей
            }

            public void newsUpdated ( SingleNews updatedNews )
            {
                newsIcon.setIcon ( updatedNews.getType ().getIcon () );

                newsTitle.setText ( "<html><b>" + updatedNews.getTitle () + "</b></html>" );

                newsText.setText ( updatedNews.getText () != null ?
                        "<html>" + updatedNews.getText () + "</html>" : null );

                newsLink.setLink ( updatedNews.getLink (), false );
                newsLink.setText ( updatedNews.getLink () );

                if ( !SettingsManager.get ( "SelectedPage", TrackerPage.sell )
                        .equals ( TrackerPage.news ) )
                {
                    slidingLayout.slideIn ();
                }
            }
        } );

        ////////////////////////////////////////////////////////////

        contentPanel = new WebPanel ();
        contentLayout = new CardLayout ();
        contentPanel.setLayout ( contentLayout );
        add ( contentPanel, "0,2" );

        ////////////////////////////////////////////////////////////

        WebPanel menuPanel = new WebPanel ( true );
        menuPanel.setShadeWidth ( 0 );
        menuPanel.setDrawSides ( false, false, true, false );
        add ( menuPanel, "0,1" );

        menu = new WebBreadcrumb ();
        menu.setOpaque ( false );
        menu.setMargin ( 7 );
        menu.setOverlap ( 11 );
        menu.setEncloseLastElement ( true );
        menuPanel.add ( menu, BorderLayout.WEST );

        pageButtons = new HashMap<TrackerPage, WebBreadcrumbToggleButton> ();
        TrackerPage[] pages = TrackerPage.values ();
        for ( int i = 0; i < pages.length; i++ )
        {
            final TrackerPage page = pages[ i ];
            if ( !page.isActive () )
            {
                continue;
            }

            BreadcrumbElementType type =
                    i == 0 ? BreadcrumbElementType.start : BreadcrumbElementType.middle;
            WebBreadcrumbToggleButton menuItem =
                    new WebBreadcrumbToggleButton ( page.getText (), page.getIcon () );
            menu.add ( menuItem );
            pageButtons.put ( page, menuItem );

            contentPanel.add ( createPage ( page ), page.toString () );
            menuItem.addActionListener ( new ActionListener ()
            {
                public void actionPerformed ( ActionEvent e )
                {
                    switchToPage ( page );
                }
            } );
        }

        ButtonGroup buttons = SwingUtils.groupButtons ( menu );
        pageButtons.get ( SettingsManager.get ( "SelectedPage", TrackerPage.news ) ).doClick ();


        final WebButton itemsCan = new WebButton ( "Корзина", itemsCanIcon );
        HotkeyManager.registerHotkey ( itemsCan, Hotkey.ALT_E );
        TooltipManager.setTooltip ( itemsCan, "Корзина итемов" );
        itemsCan.setRound ( 4 );
        itemsCan.setShadeWidth ( 4 );
        itemsCan.setDrawFocus ( false );
        itemsCan.setRolloverDecoratedOnly ( true );
        menuPanel.add ( itemsCan, BorderLayout.EAST );

        final WebButtonPopup canPopup = new WebButtonPopup ( itemsCan, PopupWay.downLeft );
        canPopup.setCloseOnFocusLoss ( false );

        WebPanel popupContent = new WebPanel ();
        popupContent.setOpaque ( false );
        popupContent.setMargin ( 2 );

        final ItemField itemSearchField = new ItemField ();
        final WebImage search = new WebImage ( TradeHelper.class, "icons/search.png" );
        itemSearchField.setTrailingComponent ( search );
        popupContent.add ( itemSearchField, BorderLayout.NORTH );

        final ItemDropList itemDropList = new ItemDropList ();
        itemDropList.setPreferredWidth ( 200 );
        itemsCan.setTransferHandler ( new ProxyDropHandler ( itemDropList ) );
        itemSearchField.addItemListener ( new com.rag.forum.ui.ItemListener ()
        {
            public void itemSelected ( Item item )
            {
                itemDropList.addItem ( item );
                itemSearchField.clear ();
                itemSearchField.requestFocusInWindow ();
            }
        } );
        itemDropList.addItems ( RagManager.getItems ( TextUtils
                .stringToList ( SettingsManager.getString ( "TradeHelper.itemsSet" ), "," ) ) );
        itemDropList.addItemSelectionListener ( new ItemSelectionListener ()
        {
            public void selectionChanged ( List<Item> items )
            {
                SettingsManager.set ( "TradeHelper.itemsSet",
                        TextUtils.listToString ( itemDropList.getItemIds (), "," ) );
            }
        } );
        popupContent.add ( itemDropList.getView ( true ), BorderLayout.CENTER );

        canPopup.setContent ( popupContent );

        itemsCan.addActionListener ( new ActionListener ()
        {
            public void actionPerformed ( ActionEvent e )
            {
                if ( canPopup.isShowing () )
                {
                    canPopup.hidePopup ();
                }
                else
                {
                    PopupManager.showPopup ( itemsCan, canPopup );
                }
            }
        } );

        ////////////////////////////////////////////////////////////

        initializeTrayIcon ();

        addWindowStateListener ( new WindowStateListener ()
        {
            public void windowStateChanged ( WindowEvent e )
            {
                if ( getState () == JFrame.ICONIFIED )
                {
                    toggleHide ();
                }
            }
        } );

        ////////////////////////////////////////////////////////////

        setDefaultCloseOperation ( JFrame.EXIT_ON_CLOSE );
        SettingsManager.registerComponent ( this, "TradeHelper.windowBounds",
                new Rectangle ( -1, -1, 1000, 800 ) );
        setVisible ( true );
    }

    private void switchToPage ( TrackerPage page )
    {
        this.page = page;
        contentLayout.show ( contentPanel, page.toString () );
        contentPanel.revalidate ();
        contentPanel.transferFocus ();
        SettingsManager.set ( "SelectedPage", page );
    }

    private JComponent createPage ( TrackerPage page )
    {
        if ( page.equals ( TrackerPage.news ) )
        {
            return new NewsPage ();
        }
        else if ( page.equals ( TrackerPage.sell ) )
        {
            return new ForumPage ( ForumType.sell, pageButtons.get ( TrackerPage.sell ) );
        }
        else if ( page.equals ( TrackerPage.buy ) )
        {
            return new ForumPage ( ForumType.buy, pageButtons.get ( TrackerPage.buy ) );
        }
        else if ( page.equals ( TrackerPage.trade ) )
        {
            return new ForumPage ( ForumType.trade, pageButtons.get ( TrackerPage.trade ) );
        }
        else if ( page.equals ( TrackerPage.rent ) )
        {
            return new ForumPage ( ForumType.rent, pageButtons.get ( TrackerPage.rent ) );
        }
        else if ( page.equals ( TrackerPage.favorites ) )
        {
            return new FavoritePage ( pageButtons.get ( TrackerPage.favorites ) );
        }
        else if ( page.equals ( TrackerPage.database ) )
        {
            return new DatabasePage ();
        }
        else
        {
            return new NewTopicPage ();
        }
    }

    private void initializeTrayIcon ()
    {
        try
        {
            trayIcon = new TrayIcon ( TradeHelper.icon );
            trayIcon.setToolTip ( "Торговые сообщения с MOTR форума" );

            trayIcon.addMouseListener ( new MouseAdapter ()
            {
                public void mousePressed ( MouseEvent e )
                {
                    if ( SwingUtilities.isLeftMouseButton ( e ) )
                    {
                        toggleHide ();
                    }
                }
            } );

            trayIcon.setPopupMenu ( new PopupMenu ()
            {
                {
                    hideItem = new MenuItem ( "Спрятать приложение" )
                    {
                        {
                            addActionListener ( new ActionListener ()
                            {
                                public void actionPerformed ( ActionEvent e )
                                {
                                    toggleHide ();
                                }
                            } );
                        }
                    };
                    add ( hideItem );
                    addSeparator ();
                    for ( final TrackerPage page : TrackerPage.values () )
                    {
                        if ( page.isActive () )
                        {
                            add ( new MenuItem ( page.getText () )
                            {
                                {
                                    addActionListener ( new ActionListener ()
                                    {
                                        public void actionPerformed ( ActionEvent e )
                                        {
                                            PopupManager.hideAllPopups ();
                                            pageButtons.get ( page ).doClick ();
                                            TradeHelper.this.setVisible ( true );
                                            TradeHelper.this.toFront ();
                                        }
                                    } );
                                }
                            } );
                        }
                    }
                    addSeparator ();
                    add ( new MenuItem ( "Форум продаж" )
                    {
                        {
                            addActionListener ( new ActionListener ()
                            {
                                public void actionPerformed ( ActionEvent e )
                                {
                                    WebUtils.browseSiteSafely ( ForumManager.sellAddress );
                                }
                            } );
                        }
                    } );
                    add ( new MenuItem ( "Форум покупок" )
                    {
                        {
                            addActionListener ( new ActionListener ()
                            {
                                public void actionPerformed ( ActionEvent e )
                                {
                                    WebUtils.browseSiteSafely ( ForumManager.buyAddress );
                                }
                            } );
                        }
                    } );
                    addSeparator ();
                    add ( new MenuItem ( "Выйти" )
                    {
                        {
                            addActionListener ( new ActionListener ()
                            {
                                public void actionPerformed ( ActionEvent e )
                                {
                                    SystemTray.getSystemTray ().remove ( trayIcon );
                                    System.exit ( 0 );
                                }
                            } );
                        }
                    } );
                }
            } );

            SystemTray.getSystemTray ().add ( trayIcon );
        }
        catch ( AWTException e )
        {
            //
        }
    }

    private void toggleHide ()
    {
        PopupManager.hideAllPopups ();
        if ( this.isShowing () )
        {
            hideItem.setLabel ( "Показать приложение" );
            this.setVisible ( false );
        }
        else
        {
            hideItem.setLabel ( "Спрятать приложение" );
            this.setState ( JFrame.NORMAL );
            this.setVisible ( true );
            this.toFront ();
        }
    }

    public HashMap<TrackerPage, WebBreadcrumbToggleButton> getPageButtons ()
    {
        return pageButtons;
    }
}